﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Glee.Drawing;
using System.Xml.Linq;
using System.IO;
using System.Threading.Tasks;
using GraphViewer.Data;
using GraphViewer.Entity;
using System.Configuration;
using GraphViewer.Configuration;
using System.Globalization;
using Microsoft.Glee.GraphViewerGdi;

namespace GraphViewer.View
{
    public partial class FormViewer : Form
    {
        #region Attributes

        private IBBA_RISCOEntities _data;
        private List<ProcessEntity> _processesSimio;
        private List<ProcessEntity> _processesControlM;
        private List<ProcessEntity> _orderedProcessesSimio;
        private List<GroupEntity> _groupsSimio;
        private List<GroupEntity> _orderedGroupsSimio;

        private Graph _graphSimio;
        private Graph _graphControlM;

        private object _selectedObjectAttr;
        private object _selectedObject;
        private ToolTip _toolTip = new ToolTip();

        private bool _showCTM;

        private EnvironmentConfigurationSection _environmentConfiguration;

        public List<ProcessEntity> OrderedProcessesSimio
        {
            get { return _orderedProcessesSimio; }
            set { _orderedProcessesSimio = value; }
        }

        public List<GroupEntity> GroupsSimio
        {
            get { return _groupsSimio; }
            set { _groupsSimio = value; }
        }

        public List<GroupEntity> OrderedGroupsSimio
        {
            get { return _orderedGroupsSimio; }
            set { _orderedGroupsSimio = value; }
        }

        public bool ShowCTM
        {
            get { return _showCTM; }
            set { _showCTM = value; }
        }

        #endregion

        #region Constructor

        public FormViewer()
        {
            InitializeComponent();

            this._toolTip.Active = true;
            _toolTip.AutoPopDelay = 5000;
            _toolTip.InitialDelay = 1000;
            _toolTip.ReshowDelay = 500;
        }

        #endregion

        #region Events

        private void FormViewer_Load(object sender, EventArgs e)
        {
            var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            _environmentConfiguration = (EnvironmentConfigurationSection)config.GetSection("environmentConfiguration");

            PopulateCombo();

            gViewerSimio.SelectionChanged += new EventHandler(gViewer_SelectionChanged);
            gViewerControlM.SelectionChanged += new EventHandler(gViewer_SelectionChanged);

            gViewerSimio.MouseEnter += new EventHandler(gViewer_MouseEnter);
            gViewerControlM.MouseEnter += new EventHandler(gViewer_MouseEnter);

            gViewerSimio.MouseWheel += new MouseEventHandler(gViewer_MouseWheel);
            gViewerControlM.MouseWheel += new MouseEventHandler(gViewer_MouseWheel);
        }

        private void gViewer_MouseEnter(object sender, EventArgs e)
        {
            Microsoft.Glee.GraphViewerGdi.GViewer gViewer = sender as Microsoft.Glee.GraphViewerGdi.GViewer;

            gViewer.Focus();
        }

        private void gViewer_MouseWheel(object sender, MouseEventArgs e)
        {
            Microsoft.Glee.GraphViewerGdi.GViewer gViewer = sender as Microsoft.Glee.GraphViewerGdi.GViewer;

            if (e.Delta > 0)
            {
                gViewer.ZoomInPressed();
            }
            else
            {
                gViewer.ZoomOutPressed();
            }
        }

        private void FormViewer_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.Modifiers & Keys.Control) > 0 && e.KeyCode == Keys.F)
            {
                FormSearch search = new FormSearch();
                if (search.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    GViewer viewer = search.IsControlMSearch ? gViewerControlM : gViewerSimio;

                    var entity = viewer.Entities.ToList().Find(o =>
                        {
                            Microsoft.Glee.Node node = o.DrawingObject.GleeObject as Microsoft.Glee.Node;
                            bool found = false;

                            if (node != null)
                            {
                                found = node.Id == search.TextToSearch;
                            }

                            return found;
                        });

                    if (entity != null)
                    {
                        if (search.IsControlMSearch)
                        {
                            viewer.ShowBBox(((Microsoft.Glee.Node)entity.DrawingObject.GleeObject).BBox);
                        }
                        else
                        {
                            viewer.ShowBBox(((Microsoft.Glee.Node)entity.DrawingObject.GleeObject).BBox);
                        }
                    }
                    else
                    {
                        MessageBox.Show("Nothing found!");
                    }
                }
            }
        }

        private void gViewer_SelectionChanged(object sender, EventArgs e)
        {
            Microsoft.Glee.GraphViewerGdi.GViewer gViewer = sender as Microsoft.Glee.GraphViewerGdi.GViewer;

            if (_selectedObject != null)
            {
                if (_selectedObject is Edge)
                {
                    (_selectedObject as Edge).Attr = _selectedObjectAttr as EdgeAttr;
                }
                else if (_selectedObject is Node)
                {
                    (_selectedObject as Node).Attr = _selectedObjectAttr as NodeAttr;
                }

                _selectedObject = null;
            }

            if (gViewer.SelectedObject == null)
            {
                gViewer.SetToolTip(_toolTip, "");
            }
            else
            {
                _selectedObject = gViewer.SelectedObject;

                if (_selectedObject is Edge)
                {
                    _selectedObjectAttr = (gViewer.SelectedObject as Edge).Attr.Clone();
                    (gViewer.SelectedObject as Edge).Attr.Color = Color.Magenta;
                    (gViewer.SelectedObject as Edge).Attr.Fontcolor = Color.Magenta;
                    Edge edge = gViewer.SelectedObject as Edge;
                    gViewer.SetToolTip(this._toolTip, String.Format("{0} -> {1}", edge.Source, edge.Target));
                }
                else if (_selectedObject is Node)
                {
                    _selectedObjectAttr = (gViewer.SelectedObject as Node).Attr.Clone();
                    (_selectedObject as Node).Attr.Color = Color.Magenta;
                    (_selectedObject as Node).Attr.Fontcolor = Color.Magenta;

                    ProcessEntity process = ((ProcessEntity)(_selectedObject as Node).UserData);

                    if (process != null)
                    {
                        gViewer.SetToolTip(_toolTip, process.ToString());
                        toolStripStatusLabel1.Text = process.ToString();
                    }
                }
            }

            gViewer.Invalidate();
        }

        private void btnHideSimio_Click(object sender, EventArgs e)
        {
            splitContainer1.Panel1Collapsed = !splitContainer1.Panel1Collapsed;
            btnHideSimio.Text = splitContainer1.Panel1Collapsed ? "=>" : "<=";
            btnHideControlM.Text = splitContainer1.Panel2Collapsed ? "<=" : "=>";
        }

        private void btnHideControlM_Click(object sender, EventArgs e)
        {
            splitContainer1.Panel2Collapsed = !splitContainer1.Panel2Collapsed;
            btnHideSimio.Text = splitContainer1.Panel1Collapsed ? "=>" : "<=";
            btnHideControlM.Text = splitContainer1.Panel2Collapsed ? "<=" : "=>";
        }

        private void btnViewSimio_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(ddlEnvironmentSimio.Text))
                {
                    MessageBox.Show("Selecione um ambiente!");
                }
                else
                {
                    _showCTM = false;
                    GenerateSimioGraph();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void btnViewCTM_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(ddlEnvironmentSimio.Text))
                {
                    MessageBox.Show("Selecione um ambiente!");
                }
                else
                {
                    _showCTM = true;
                    GenerateSimioGraph();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void btnExporter_Click(object sender, EventArgs e)
        {
            if (_processesSimio != null)
            {
                if (string.IsNullOrWhiteSpace(ddlEnvironmentControlM.Text))
                {
                    MessageBox.Show("Selecione o ambiente do Control-M que deseja exportar.");
                }
                else
                {
                    SaveFileDialog dialog = new SaveFileDialog();

                    dialog.Filter = "XML Files (*.xml)|*.xml";
                    dialog.Title = "Save Jobs";
                    dialog.RestoreDirectory = true;

                    if (dialog.ShowDialog() == DialogResult.OK)
                    {
                        Export(dialog.FileName, ddlEnvironmentControlM.Text);
                    }
                }
            }
            else
            {
                MessageBox.Show("Faça uma pesquisa antes de exportar!");
            }
        }

        private void btnImport_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();

            dialog.Filter = "XML Files (*.xml)|*.xml";
            dialog.Title = "Open Jobs";
            dialog.RestoreDirectory = true;

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                GenerateControlMGraph(dialog.FileName);
            }
        }

        #endregion

        #region Methods

        #region Simio

        private void GenerateSimioGraph()
        {
            _graphSimio = new Graph("graphSimio");

            PopulateData();

            foreach (GroupEntity group in _groupsSimio)
            {
                DrawingGroup(group);
            }

            foreach (GroupEntity group in _groupsSimio)
            {
                if (group.Dependencies.Count > 0)
                {
                    foreach (var groupDependendy in group.Dependencies)
                    {
                        Edge edge = _graphSimio.AddEdge(GetDummyJobName(false, groupDependendy), "Grupo " + group.GroupId.ToString());

                        _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, group.GroupId)).Predecessors.Add(GetDummyJobName(false, groupDependendy));
                    }
                }
                else
                {
                    var firstGroupProcess = _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, group.GroupId));
                    firstGroupProcess.Predecessors.Add("LIBERA_BUILD_FORGE_RISCO");
                }

                if (!_groupsSimio.Exists(g => g.Dependencies.Exists(d => d == group.GroupId)))
                {
                    _processesSimio.Find(p => p.ProcessId == "RSCISDFIDP").Predecessors.Add(GetDummyJobName(false, group.GroupId));
                    AddEdgeExternalSuccessorJob(GetDummyJobName(false, group.GroupId), "RSCISDFIDP", "200");
                }
            }

            if (_showCTM)
            {
                _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, "30")).Predecessors.Add("RSCIS003DP"); //30 - IMPORTAÇÃO - IBA OPERACOES
                _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, "29")).Predecessors.Add("RSCIS004DP"); //29 - IMPORTAÇÃO - ITAU OPERACOES
                _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, "31")).Predecessors.Add("RSCIS005DP"); //31 - IMPORTAÇÃO - ITAU GARANTIAS
                _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, "28")).Predecessors.Add("RSCIS006DP"); //28 -  Itau: Carga das propostas 
                _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, "0")).Predecessors.Add("SCGIS000DP"); //0 - AGENDAMENTO
                _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, "24")).Predecessors.Add("MOITSF61DP"); //24 - IMPORTAÇÃO - SCG
                _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, "24")).Predecessors.Add("SCGIS008DP"); //24 - IMPORTAÇÃO - SCG
                _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, "24")).Predecessors.Add("LIBERA_RISCO_CREDITO"); //24 - IMPORTAÇÃO - SCG
                _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, "33")).Predecessors.Add("LIBERA_RISCO_CREDITO"); //33 - IMPORTAÇÃO - MO PREVALENCIA

                AddEdgeExternalPredecessorJob("LIBERA_BUILD_FORGE_RISCO", "Grupo 0", "160");
                AddEdgeExternalPredecessorJob("SCGIS000DP", "Grupo 0", "160");
                AddEdgeExternalPredecessorJob("RSCIS003DP", "Grupo 30", "120");
                AddEdgeExternalPredecessorJob("RSCIS004DP", "Grupo 29", "130");
                AddEdgeExternalPredecessorJob("RSCIS005DP", "Grupo 31", "140");
                AddEdgeExternalPredecessorJob("RSCIS006DP", "Grupo 28", "150");
                AddEdgeExternalPredecessorJob("MOITSF61DP", "Grupo 24", "170");
                AddEdgeExternalPredecessorJob("SCGIS008DP", "Grupo 24", "170");
                AddEdgeExternalPredecessorJob("LIBERA_RISCO_CREDITO", "Grupo 24", "170");
                AddEdgeExternalPredecessorJob("LIBERA_RISCO_CREDITO", "Grupo 33", "180");
            }

            PopulateSuccessors();

            _processesSimio.Find(p => p.ProcessId == GetDummyJobName(false, "6")).Successors.Add("RARDS009DP");
            AddEdgeExternalSuccessorJob(GetDummyJobName(false, "6"), "RARDS009DP", "210");

            _processesSimio.Find(p => p.ProcessId == "RSCISDFIDP").Successors.Add("PRODSRSCDP");
            AddEdgeExternalSuccessorJob("RSCISDFIDP", "PRODSRSCDP", "220");

            gViewerSimio.Graph = _graphSimio;
            gViewerSimio.CalculateLayout(_graphSimio);
        }

        private void AddEdgeExternalPredecessorJob(string predecessorJobName, string successorJobName, string groupId)
        {
            Edge edge = _graphSimio.AddEdge(predecessorJobName, successorJobName);
            SetStyle(edge.SourceNode, Shape.Ellipse, groupId);
        }

        private void AddEdgeExternalSuccessorJob(string predecessorJobName, string successorJobName, string groupId)
        {
            Edge edge = _graphSimio.AddEdge(predecessorJobName, successorJobName);
            SetStyle(edge.TargetNode, Shape.Ellipse, groupId);
        }

        private void DrawingGroup(GroupEntity group)
        {
            Node node = _graphSimio.AddNode("Grupo " + group.GroupId.ToString());
            Node startNode = _graphSimio.AddNode(GetDummyJobName(true, group.GroupId));
            Node endNode = _graphSimio.AddNode(GetDummyJobName(false, group.GroupId));

            node.Attr.Label = group.GroupId + " - " + group.GroupName;
            startNode.Attr.Label = string.Empty;
            endNode.Attr.Label = string.Empty;

            foreach (var process in _processesSimio.Where(p => p.GroupId == group.GroupId))
            {
                if (process.Predecessors.Count > 0)
                {
                    foreach (var predecessor in process.Predecessors)
                    {
                        Edge edge = _graphSimio.AddEdge(predecessor, process.ProcessId);

                        SetStyle(edge.SourceNode, Shape.Circle, process.GroupId);
                        SetStyle(edge.TargetNode, Shape.Circle, process.GroupId);

                        edge.TargetNode.UserData = new ProcessEntity() { ProcessId = process.ProcessId, ProcessName = process.ProcessName };
                    }
                }
            }

            SetStyle(node, Shape.Box, group.GroupId);
            SetStyle(startNode, Shape.Point, Color.Black);
            SetStyle(endNode, Shape.Point, Color.Black);

            _graphSimio.AddEdge(node.Id, startNode.Id);
        }

        private void PopulateData()
        {
            string environment = ddlEnvironmentSimio.Invoke(new Func<string>(() => { return ddlEnvironmentSimio.Text; })).ToString();

            PopulateData(environment);
        }

        public void PopulateData(string environment)
        {
            string connectionString = "metadata=res://*/Data.IBBA_RISCOEntities.csdl|res://*/Data.IBBA_RISCOEntities.ssdl|res://*/Data.IBBA_RISCOEntities.msl;provider=System.Data.SqlClient;provider connection string='Data Source={0};Initial Catalog=IBBA_RISCO;Integrated Security=True;Connection Timeout=60;multipleactiveresultsets=true'";

            _data = new IBBA_RISCOEntities(string.Format(connectionString, environment));
            _groupsSimio = new List<GroupEntity>();
            _processesSimio = new List<ProcessEntity>();
            _orderedProcessesSimio = new List<ProcessEntity>();
            _orderedGroupsSimio = new List<GroupEntity>();

            PopulateGroups();
            PopulateProcess();
            PopulateDummyJobs();

            foreach (var group in _groupsSimio)
            {
                if (group.Dependencies.Count > 0)
                {
                    OrderGroups(group);
                }
            }

            foreach (var process in _processesSimio)
            {
                if (process.Predecessors.Count > 0)
                {
                    OrderProcesses(process);
                }
            }
        }

        private void PopulateGroups()
        {
            List<GroupDB> groupDB;

            if (_showCTM)
            {
                groupDB = (from p in _data.SRC_GRUPO_PROCESSO_CTM
                           join d in _data.SRC_GRUPO_DEPENDENCIA_CTM
                               on p.ID_GRUPO_PROCESSO equals d.ID_GRUPO_PROCESSO into pd
                           from d1 in pd.DefaultIfEmpty()
                           where p.IC_ATIVO == true && p.ID_SISTEMA == 1
                           orderby p.ID_GRUPO_PROCESSO
                           select new GroupDB { GroupId = p.ID_GRUPO_PROCESSO, GroupName = p.NM_GRUPO_PROCESSO, PredecessorId = (d1 == null ? 0 : d1.ID_DEPENDENCIA) }).ToList();
            }
            else
            {
                groupDB = (from p in _data.SRC_GRUPO_PROCESSO
                           join d in _data.SRC_GRUPO_DEPENDENCIA
                               on p.ID_GRUPO_PROCESSO equals d.ID_GRUPO_PROCESSO into pd
                           from d1 in pd.DefaultIfEmpty()
                           where p.IC_ATIVO == true && p.ID_SISTEMA == 1
                           orderby p.ID_GRUPO_PROCESSO
                           select new GroupDB { GroupId = p.ID_GRUPO_PROCESSO, GroupName = p.NM_GRUPO_PROCESSO, PredecessorId = (d1 == null ? 0 : d1.ID_DEPENDENCIA) }).ToList();
            }

            groupDB.Add(new GroupDB { GroupId = 0, GroupName = "PREPARAR PROCESSAMENTO", PredecessorId = -1 });

            foreach (var group in groupDB)
            {
                ProcessEntity startProcessGroup = _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, group.GroupId.ToString()));
                ProcessEntity endProcessGroup = _processesSimio.Find(p => p.ProcessId == GetDummyJobName(false, group.GroupId.ToString()));
                GroupEntity entity = _groupsSimio.Find(p => p.GroupId == group.GroupId.ToString());

                if (entity == null)
                {
                    if (group.PredecessorId == -1)
                    {
                        _groupsSimio.Add(new GroupEntity() { GroupId = group.GroupId.ToString(), GroupName = group.GroupName });
                    }
                    else
                    {
                        _groupsSimio.Add(new GroupEntity() { GroupId = group.GroupId.ToString(), GroupName = group.GroupName, Dependencies = new List<string>() { group.PredecessorId.ToString() } });
                    }
                }
                else
                {
                    entity.Dependencies.Add(group.PredecessorId.ToString());
                }

                if (startProcessGroup == null)
                {
                    _processesSimio.Add(new ProcessEntity() { GroupId = group.GroupId.ToString(), ProcessId = GetDummyJobName(true, group.GroupId.ToString()), JobName = GetDummyJobName(true, group.GroupId.ToString()), TaskType = "Dummy", ProcessName = group.GroupName + " - Inicio Processamento" });
                }

                if (endProcessGroup == null)
                {
                    _processesSimio.Add(new ProcessEntity() { GroupId = group.GroupId.ToString(), ProcessId = GetDummyJobName(false, group.GroupId.ToString()), JobName = GetDummyJobName(false, group.GroupId.ToString()), TaskType = "Dummy", ProcessName = group.GroupName + " - Fim Processamento" });
                }
            }
        }

        private void PopulateProcess()
        {
            List<ProcessDB> processesDB;

            if (_showCTM)
            {
                processesDB = (from p in _data.SRC_PROCESSO_CTM
                               join d in _data.SRC_PROCESSO_DEPENDENCIA_CTM
                                   on p.ID_PROCESSO equals d.ID_PROCESSO into pd
                               from d1 in pd.DefaultIfEmpty()
                               where p.IC_ATIVO == true && p.ID_SISTEMA == 1
                               orderby p.ID_GRUPO_PROCESSO, p.ID_PROCESSO
                               select new ProcessDB { GroupId = p.ID_GRUPO_PROCESSO, ProcessId = p.ID_PROCESSO, ProcessName = p.NM_PROCESSO, JobName = p.NM_JOB, PredecessorId = (d1 == null ? -1 : d1.ID_DEPENDENCIA) }).ToList();
            }
            else
            {
                processesDB = (from p in _data.SRC_PROCESSO
                               join d in _data.SRC_PROCESSO_DEPENDENCIA
                                   on p.ID_PROCESSO equals d.ID_PROCESSO into pd
                               from d1 in pd.DefaultIfEmpty()
                               where p.IC_ATIVO == true && p.ID_SISTEMA == 1
                               orderby p.ID_GRUPO_PROCESSO, p.ID_PROCESSO
                               select new ProcessDB { GroupId = p.ID_GRUPO_PROCESSO, ProcessId = p.ID_PROCESSO, ProcessName = p.NM_PROCESSO, JobName = p.NM_JOB, PredecessorId = (d1 == null ? -1 : d1.ID_DEPENDENCIA) }).ToList();
            }

            foreach (var process in processesDB)
            {
                ProcessEntity entity = _processesSimio.Find(p => p.ProcessId == process.ProcessId.ToString());

                if (entity == null)
                {
                    if (process.PredecessorId == -1)
                    {
                        _processesSimio.Add(new ProcessEntity() { GroupId = process.GroupId.ToString(), ProcessId = process.ProcessId.ToString(), ProcessName = process.ProcessName, JobName = process.JobName, TaskType = "Job" });
                    }
                    else
                    {
                        _processesSimio.Add(new ProcessEntity() { GroupId = process.GroupId.ToString(), ProcessId = process.ProcessId.ToString(), ProcessName = process.ProcessName, JobName = process.JobName, Predecessors = new List<string>() { process.PredecessorId.ToString() }, TaskType = "Job" });
                    }
                }
                else
                {
                    entity.Predecessors.Add(process.PredecessorId.ToString());
                }
            }
        }

        private void PopulateDummyJobs()
        {
            _processesSimio.Add(new ProcessEntity() { GroupId = "0", ProcessId = "RSCIS064DP", JobName = "RSCIS064DP", TaskType = "Job", ProcessName = "Agendamento" });
            _processesSimio.Add(new ProcessEntity() { GroupId = "liberarisco", ProcessId = "LIBERA_BUILD_FORGE_RISCO", JobName = "LIBERA_BUILD_FORGE_RISCO", TaskType = "Dummy", ProcessName = "Confirme atualizações que afetam o batch do Risco de Crédito." });
            _processesSimio.Add(new ProcessEntity() { GroupId = "liberarisco", ProcessId = "LIBERA_RISCO_CREDITO", JobName = "LIBERA_RISCO_CREDITO", TaskType = "Dummy", ProcessName = "Confirme termino das dependencias para inicio do batch do Risco de Crédito." });
            _processesSimio.Add(new ProcessEntity() { GroupId = "FI", ProcessId = "RSCISDFIDP", JobName = "RSCISDFIDP", TaskType = "Dummy", ProcessName = "Final do Fluxo." });
            _processesSimio.Add(new ProcessEntity() { GroupId = "Arquivos", ProcessId = "RSCIS003DP", JobName = "RSCIS003DP", TaskType = "Job", ProcessName = "CF_RISCOS_ARGENTINA.TXT" });
            _processesSimio.Add(new ProcessEntity() { GroupId = "Arquivos", ProcessId = "RSCIS004DP", JobName = "RSCIS004DP", TaskType = "Job", ProcessName = "CF_RISCOS.TXT" });
            _processesSimio.Add(new ProcessEntity() { GroupId = "Arquivos", ProcessId = "RSCIS005DP", JobName = "RSCIS005DP", TaskType = "Job", ProcessName = "GG_GARANTIAS.TXT" });
            _processesSimio.Add(new ProcessEntity() { GroupId = "Arquivos", ProcessId = "RSCIS006DP", JobName = "RSCIS006DP", TaskType = "Job", ProcessName = "CF_PROPOSTA.TXT" });
            _processesSimio.Add(new ProcessEntity() { GroupId = "liberarisco", ProcessId = "SCGIS000DP", JobName = "SCGIS000DP", TaskType = "Dummy", ProcessName = "Job que inicia o processamento do SCG.", IsExternalJob = true });
            _processesSimio.Add(new ProcessEntity() { GroupId = "liberarisco", ProcessId = "SCGIS008DP", JobName = "SCGIS008DP", TaskType = "Dummy", ProcessName = "Job que gera o arquivo de garantias para o RSC.", IsExternalJob = true });
            _processesSimio.Add(new ProcessEntity() { GroupId = "liberarisco", ProcessId = "MOITSF61DP", JobName = "MOITSF61DP", TaskType = "Dummy", ProcessName = "Job que finaliza o processamento do MO Carteira.", IsExternalJob = true });
            //_processesSimio.Add(new ProcessEntity() { GroupId = "liberarisco", ProcessId = "LIBERA_MO_NASSAU_DP", JobName = "LIBERA_MO_NASSAU_DP", TaskType = "Dummy", ProcessName = "Job que finaliza o processamento do MO Nassau.", IsExternalJob = true });
            //_processesSimio.Add(new ProcessEntity() { GroupId = "liberarisco", ProcessId = "LIBERA_MO_CARTEIRA_DP", JobName = "LIBERA_MO_CARTEIRA_DP", TaskType = "Dummy", ProcessName = "Job que finaliza o processamento do MO Carteira.", IsExternalJob = true });

            foreach (var group in _groupsSimio)
            {
                ProcessEntity startProcessGroup = _processesSimio.Find(p => p.ProcessId == GetDummyJobName(true, group.GroupId));
                ProcessEntity endProcessGroup = _processesSimio.Find(p => p.ProcessId == GetDummyJobName(false, group.GroupId));

                foreach (var process in _processesSimio.Where(p => p.GroupId == group.GroupId))
                {
                    if (process.Predecessors.Count == 0 && process.ProcessId != startProcessGroup.ProcessId && process.ProcessId != endProcessGroup.ProcessId)
                    {
                        process.Predecessors.Add(startProcessGroup.ProcessId);
                    }

                    if (!_processesSimio.Exists(p => p.Predecessors.Exists(d => d == process.ProcessId)) && process.ProcessId != startProcessGroup.ProcessId && process.ProcessId != endProcessGroup.ProcessId)
                    {
                        endProcessGroup.Predecessors.Add(process.ProcessId);
                    }
                }
            }
        }

        private void PopulateSuccessors()
        {
            foreach (var process in _processesSimio)
            {
                process.Successors = (from p in _processesSimio
                                      from d in p.Predecessors
                                      where d == process.ProcessId
                                      select p.ProcessId).Distinct().ToList();
            }

            foreach (var process in _orderedProcessesSimio)
            {
                process.Successors = (from p in _processesSimio
                                      from d in p.Predecessors
                                      where d == process.ProcessId
                                      select p.ProcessId).Distinct().ToList();
            }
        }

        private string GetDummyJobName(bool startJob, string groupId)
        {
            //return string.Format("RSCIS{0}{1}DP", startJob ? "I" : "F", groupId.PadLeft(2, '0'));

            if (startJob)
            {
                return string.Format("RSCIS{0}{1}DP", "I", groupId.PadLeft(2, '0'));
            }
            else
            {
                if (groupId.Length == 1)
                    return string.Format("RSCISDM{0}DP", groupId);
                else
                    return string.Format("RSCISD{0}DP", groupId);
            }
        }

        private void OrderGroups(GroupEntity entity)
        {
            foreach (string predecessor in entity.Dependencies)
            {
                GroupEntity groupDependency = _groupsSimio.Find(p => p.GroupId == predecessor);

                if (groupDependency != null && entity.Dependencies.Count > 0)
                {
                    OrderGroups(groupDependency);
                }
            }

            if (_orderedGroupsSimio.Find(p => p.GroupId == entity.GroupId) == null)
            {
                _orderedGroupsSimio.Add(entity);
            }
        }

        private void OrderProcesses(ProcessEntity entity)
        {
            foreach (string predecessor in entity.Predecessors)
            {
                ProcessEntity processDependency = _processesSimio.Find(p => p.ProcessId == predecessor);

                if (processDependency != null && entity.Predecessors.Count > 0)
                {
                    OrderProcesses(processDependency);
                }
            }

            if (_orderedProcessesSimio.Find(p => p.ProcessId == entity.ProcessId) == null)
            {
                _orderedProcessesSimio.Add(entity);
            }
        }

        #endregion

        #region Control-M

        private void GenerateControlMGraph(string fileName)
        {
            _graphControlM = new Graph("graphControlM");

            ReadControlMXml(fileName);

            foreach (var process in _processesControlM)
            {
                if (process.Predecessors.Count > 0)
                {
                    foreach (var processDependendy in process.Predecessors)
                    {
                        Edge edge = _graphControlM.AddEdge(processDependendy, process.ProcessId);

                        var processDependendyFound = _processesControlM.Find(p => p.ProcessId == processDependendy);

                        if (processDependendyFound != null)
                        {
                            SetStyle(processDependendyFound, edge.SourceNode);
                        }

                        SetStyle(process, edge.TargetNode);

                        edge.TargetNode.UserData = new ProcessEntity() { ProcessId = process.ProcessId, ProcessName = process.ProcessName };
                    }
                }
                else
                {
                    Node node = _graphControlM.AddNode(process.ProcessId);

                    node.UserData = new ProcessEntity() { ProcessId = process.ProcessId, ProcessName = process.ProcessName };

                    SetStyle(process, node);
                    //SetStyle(node, Shape.Box, process.GroupName);
                }

                if (process.Successors.Count > 0)
                {
                    foreach (var successor in process.Successors)
                    {
                        _graphControlM.AddEdge(process.ProcessId, successor);
                    }
                }
            }

            gViewerControlM.Graph = _graphControlM;
            gViewerControlM.CalculateLayout(_graphControlM);
        }

        private void ReadControlMXml(string fileName)
        {
            XDocument document = XDocument.Load(fileName);

            //List<XElement> elements = new List<XElement>();
            //List<Tuple<int, int>> processesDependency = new List<Tuple<int, int>>();
            //List<int> processes = new List<int>();

            //if (File.Exists(@"c:\depedencia.sql"))
            //    File.Delete(@"c:\depedencia.sql");

            //if (File.Exists(@"c:\processo.txt"))
            //    File.Delete(@"c:\processo.txt");

            _processesControlM = new List<ProcessEntity>();

            var nodes = document.Descendants().Where(n => n.Name.LocalName == "JOB");

            foreach (var jobNode in nodes)
            {
                ProcessEntity entity = new ProcessEntity();
                entity.ProcessName = jobNode.Attribute("DESCRIPTION").Value.ToString();
                entity.ProcessId = jobNode.Attribute("JOBNAME").Value.ToString();
                entity.GroupName = jobNode.Attribute("GROUP").Value.ToString();
                entity.TaskType = jobNode.Attribute("TASKTYPE").Value.ToString();

                foreach (var dependencyNode in jobNode.Elements().Where(n => n.Name.LocalName == "INCOND"))
                {
                    string dependencyName = dependencyNode.Attribute("NAME").Value.Replace("#", "");
                    string[] jobs = dependencyName.Split('-');

                    if (jobs.Length == 2 && jobs[1] == entity.ProcessId)
                    {
                        var predecessor = nodes.ToList().Find(n => n.Attribute("JOBNAME").Value == jobs[0]);

                        if (predecessor != null)
                        {
                            //entity.Predecessors.Add(jobs[0]);
                            entity.Predecessors.Add(FindProcessId(predecessor));
                            //WriteProcessDependency(processesDependency, jobNode, predecessor);
                        }
                        else
                        {
                            entity.Predecessors.Add(jobs[0]);
                        }
                    }
                }

                foreach (var dependencyNode in jobNode.Elements().Where(n => n.Name.LocalName == "OUTCOND" && n.Attributes().Any(a => a.Name.LocalName == "SIGN" && a.Value == "ADD")))
                {
                    string[] jobs = dependencyNode.Attribute("NAME").Value.Split('-');

                    var successor = nodes.ToList().Find(n => n.Attribute("JOBNAME").Value == jobs[1]);

                    if (successor == null)
                    {
                        entity.Successors.Add(jobs[1]);
                    }
                }

                entity.ProcessId = FindProcessId(jobNode);

                _processesControlM.Add(entity);

                //WriteProcess(processes, jobNode);

                //elements.Add(jobNode);
            }

            //foreach (var jobNode in document.Descendants().Where(n => n.Name.LocalName == "OUTCOND"))
            //{
            //    var a = jobNode.Attribute("NAME").Value.Split('-');

            //    File.AppendAllText(@"c:\teste\jobs.txt", a[0] + System.Environment.NewLine);
            //    File.AppendAllText(@"c:\teste\jobs.txt", a[1] + System.Environment.NewLine);
            //}

            document.Save(fileName);
        }

        private void WriteProcessDependency(List<Tuple<int, int>> processes, XElement jobNode, XElement predecessor)
        {
            int processId = 0;
            int predecessorId = 0;

            string processName = FindProcessId(jobNode);
            string predecessorName = FindProcessId(predecessor);

            int.TryParse(processName, out processId);
            int.TryParse(predecessorName, out predecessorId);

            Tuple<int, int> tuple = processes.Find(t => t.Item1 == processId && t.Item2 == predecessorId);

            if (tuple == null)
            {
                if (processId != 0 && predecessorId != 0)
                {
                    processes.Add(new Tuple<int, int>(processId, predecessorId));

                    File.AppendAllText(@"c:\depedencia.sql", "INSERT SRC_PROCESSO_DEPENDENCIA_CTM VALUES (" + processId + "," + predecessorId + ")" + System.Environment.NewLine);
                }
            }
        }

        private void WriteProcess(List<int> processes, XElement jobNode)
        {
            int processId = 0;
            string processName = FindProcessId(jobNode);
            int.TryParse(processName, out processId);

            if (processId != 0 && processes.Find(p => p == processId) == 0)
            {
                processes.Add(processId);

                File.AppendAllText(@"c:\processo.txt", processId + System.Environment.NewLine);
            }
        }

        private string FindProcessId(XElement jobName)
        {
            string processName = string.Empty;

            if (jobName.Elements().Any(n => n.Name.LocalName == "AUTOEDIT" && n.Attributes().Any(a => a.Name.LocalName == "EXP")))
            {
                int processId = 0;
                var parameterNode = jobName.Elements().Where(n => n.Name.LocalName == "AUTOEDIT" && n.Attribute("EXP").Value.StartsWith("%%PARM5")).SingleOrDefault();

                if (parameterNode != null)
                {
                    processName = parameterNode.Attribute("EXP").Value.Replace("%%PARM5=-id:", "");

                    int.TryParse(processName, out processId);

                    if (processId != 0)
                    {
                        processName = processId.ToString();
                    }
                    else
                    {
                        processName = string.Empty;
                    }
                }
            }

            if (string.IsNullOrEmpty(processName))
            {
                processName = jobName.Attribute("JOBNAME").Value;
            }

            return processName;
        }

        private void OrderControlMXml(string fileName, List<XElement> elements)
        {
            XDocument orderedDocument = XDocument.Load(fileName);

            var tableElement = orderedDocument.Descendants().Where(n => n.Name.LocalName == "SCHED_TABLE").First();

            tableElement.RemoveNodes();

            foreach (var process in _processesControlM)
            {
                if (process.Predecessors.Count > 0)
                {
                    OrderProcesses(process);
                }
            }

            foreach (var process in _orderedProcessesSimio)
            {
                var jobName = elements.Find(n => n.Attribute("JOBNAME").Value.ToString() == process.ProcessId);

                tableElement.Add(jobName);
            }

            orderedDocument.Save(@"c:\teste\a.xml");
        }

        #endregion

        #region Export

        private void Export(string fileName, string environment)
        {
            ControlMConfigurationElement controlMConfiguration = _environmentConfiguration.ControlM[environment];

            XDocument document = new XDocument(
                    new XDocumentType("DEFTABLE", null, "deftable.dtd", null),
                    XElement.Parse(@"                
                            <DEFTABLE>
                                <SCHED_TABLE DATACENTER='BBACTMC2' LAST_UPLOAD='22/12/2011 20:29:23' TABLE_NAME='BBAMTSN_NLB_RSCI_SYSTEM' TABLE_USERDAILY='SYSTEM' USED_BY='ratorres' USED_BY_CODE='36536'>
                                </SCHED_TABLE>
                            </DEFTABLE>")
                    );

            document.Declaration = new XDeclaration("1.0", "ISO-8859-1", null);

            string elementBase = @"
                <JOB APPLICATION='BBAMTSN_NLB_RSCI' APR='1' AUG='1' AUTHOR='odlopes' AUTOARCH='0' CHANGE_DATE='20111128' CHANGE_TIME='101542' CHANGE_USERID='odlopes' CONFIRM='0' CREATION_DATE='20110923' CREATION_TIME='161854' CREATION_USER='odlopes' CRITICAL='0' CYCLIC='0' CYCLIC_TYPE='Interval' DAYS_AND_OR='OR' DEC='1' DESCRIPTION='PREPARAR PROCESSAMENTO - GRP_001 ITAU: CARGA DAS OPERACOES' FEB='1' GROUP='NORISKSG01' IND_CYCLIC='START' INTERVAL='00001M' JAN='1' JOBNAME='RSCIS065DP' JUL='1' JUN='1' MAR='1' MAXDAYS='0' MAXRERUN='0' MAXRUNS='0' MAXWAIT='30' MAY='1' MEMLIB='\\BBACTMC2\JOBCTL\%%PARM9.\RSCI\SHELLIB' MEMNAME='EXEC_PROG_RSCI.cmd' MULTY_AGENT='N' NODEID='BBARISCO' NOV='1' OCT='1' OPTION='Copy' OWNER='controlm' PAR='\\bbactmc2\JOBCTL\%%PARM9.\RSCI\LOG\%%JOBNAME._%%ODATE._%%TIME..txt' PRIORITY='AA' RETRO='0' SEP='1' SHIFT='IGNOREJOB' SHIFTNUM='+00' SYSDB='0' TASKTYPE='Job' USE_INSTREAM_JCL='N' WEEKDAYS='1,2,3,4,5' WEEKSCAL='ALLDAYS'>
                    <QUANTITATIVE NAME='INIT' QUANT='1' />
                    <QUANTITATIVE NAME='RSCI_PROD' QUANT='1' />
                    <AUTOEDIT EXP='%%PARM1=%%JOBNAME' />
                    <AUTOEDIT EXP='%%PARM2=ibba.src.console.exe' />
                    <AUTOEDIT EXP='%%PARM3=-servidor:%%COMPUTERNAME%%' />
                    <AUTOEDIT EXP='%%PARM4=-tipo:comando'/>
                    <AUTOEDIT EXP='%%PARM5=-id:1'/>
                    <AUTOEDIT EXP='%%PARM6=-ref:%%$OYEAR.-%%OMONTH.-%%ODAY.' />
                    <AUTOEDIT EXP='%%PARM9=1' />
                    <ON CODE='*MSG_Sucesso*' STMT='*'>
                    <DO ACTION='OK' />
                    </ON>
                    <ON CODE='*MSG_Semarq_Prog*' STMT='*'>
                    <DO ACTION='NOTOK' />
                    <DOMAIL ATTACH_SYSOUT='Yes' CC_DEST='IBBA-ProcessamentoRisco@corp.bba.com.br;producao@itaubba.com.br' DEST='IBBA-Control-M@itaubba.com.br' MESSAGE='{0} Programa %%PARM2. nao encontrado no diretorio -- Job = %%JOBNAME - %%PARM5 - %%PARM6' SUBJECT='[CTM] *** Alerta: Erro: RSCI - PREPARAR PROCESSAMENTO - JOBNAME - {0} ***' URGENCY='V' />
                    </ON>
                    <ON CODE='*MSG_ErroProg*' STMT='*'>
                    <DO ACTION='NOTOK' />
                    <DOMAIL ATTACH_SYSOUT='Yes' CC_DEST='IBBA-ProcessamentoRisco@corp.bba.com.br;producao@itaubba.com.br' DEST='IBBA-Control-M@itaubba.com.br' MESSAGE='{0} Erro no programa %%PARM2., consultar anexo. -- Job = %%JOBNAME - %%PARM5 - %%PARM6' SUBJECT='[CTM] *** Alerta: Erro: RSCI - PREPARAR PROCESSAMENTO - JOBNAME - {0} ***' URGENCY='V' />
                    </ON>
                </JOB>
                ";

            var tableElement = document.Descendants().Where(n => n.Name.LocalName == "SCHED_TABLE").First();
            tableElement.Attribute("TABLE_NAME").Value = controlMConfiguration.TableName;

            foreach (var process in _processesSimio.Where(p => !p.IsExternalJob))
            {
                string description = RemoveAccents("GRP_" + process.GroupId.PadLeft(3, '0') + " " + process.ProcessName);
                string jobName = ReplaceJobName(process.JobName, controlMConfiguration.JobNameSuffix);

                XElement element = XElement.Parse(elementBase);

                element.Attribute("DESCRIPTION").Value = description;
                element.Attribute("JOBNAME").Value = jobName;
                element.Attribute("GROUP").Value = process.GroupId == "liberarisco" ? "liberarisco" : "NORISKSG" + process.GroupId.PadLeft(2, '0');
                element.Attribute("TASKTYPE").Value = process.TaskType;
                element.Attribute("NODEID").Value = controlMConfiguration.NodeId;
                element.Attribute("APPLICATION").Value = controlMConfiguration.Application;

                element.Attribute("CHANGE_DATE").Value = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString().PadLeft(2, '0') + DateTime.Now.Day.ToString().PadLeft(2, '0');
                element.Attribute("CHANGE_TIME").Value = DateTime.Now.Hour.ToString().PadLeft(2, '0') + DateTime.Now.Minute.ToString().PadLeft(2, '0') + DateTime.Now.Second.ToString().PadLeft(2, '0');
                element.Attribute("CHANGE_USERID").Value = "llleme";

                element.Elements().Single(e => e.Name.LocalName == "QUANTITATIVE" && e.Attribute("NAME").Value == "RSCI_PROD").Attribute("NAME").Value = "RSCI_" + environment;

                if (jobName == "LIBERA_BUILD_FORGE_RISCO")
                {
                    element.Attribute("APPLICATION").Value = "LIBERA_BF_RISCO";
                    element.Add(new XAttribute("DAYSCAL", "WORKDAYS"));
                    element.Attribute("CONFIRM").Value = "1";
                    element.Attribute("WEEKDAYS").Remove();
                    element.Attribute("WEEKSCAL").Remove();
                    element.Attribute("MEMLIB").Remove();
                    element.Attribute("MEMNAME").Remove();
                }

                if (jobName == "LIBERA_RISCO_CREDITO")
                {
                    element.Attribute("APPLICATION").Value = "LIBERA_RISCO_CREDITO";
                    element.Attribute("CONFIRM").Value = "1";
                    element.Attribute("MEMLIB").Remove();
                    element.Attribute("MEMNAME").Remove();
                }

                foreach (var jobDependency in process.Predecessors)
                {
                    XElement incond = new XElement("INCOND");
                    XAttribute and = new XAttribute("AND_OR", "AND");
                    XAttribute name = new XAttribute("NAME", ReplaceJobName(_processesSimio.Find(g => g.ProcessId == jobDependency).JobName, controlMConfiguration.JobNameSuffix) + "-" + jobName);
                    XAttribute odate = new XAttribute("ODATE", "ODAT");
                    incond.Add(and);
                    incond.Add(name);
                    incond.Add(odate);
                    element.Add(incond);

                    XElement outcond = new XElement("OUTCOND");
                    XAttribute sign = new XAttribute("SIGN", "DEL");
                    outcond.Add(name);
                    outcond.Add(odate);
                    outcond.Add(sign);
                    element.Add(outcond);

                    if (jobDependency == "RSCIS003DP" || jobDependency == "RSCIS004DP" || jobDependency == "RSCIS005DP" || jobDependency == "RSCIS006DP")
                    {
                        XElement incondLB = new XElement("INCOND");
                        XAttribute nameLB = new XAttribute("NAME", name.Value + "-LB");
                        incondLB.Add(and);
                        incondLB.Add(nameLB);
                        incondLB.Add(odate);
                        element.Add(incondLB);

                        XElement outcondLB = new XElement("OUTCOND");
                        outcondLB.Add(nameLB);
                        outcondLB.Add(odate);
                        outcondLB.Add(sign);
                        element.Add(outcondLB);
                    }
                }

                foreach (var jobDependency in process.Successors)
                {
                    var job = _processesSimio.Find(g => g.ProcessId == jobDependency);

                    XElement outcond = new XElement("OUTCOND");
                    XAttribute name = new XAttribute("NAME", jobName + "-" + ReplaceJobName(job != null ? job.JobName : jobDependency, controlMConfiguration.JobNameSuffix));
                    XAttribute odate = new XAttribute("ODATE", "ODAT");
                    XAttribute sign = new XAttribute("SIGN", "ADD");

                    outcond.Add(name);
                    outcond.Add(odate);
                    outcond.Add(sign);

                    element.Add(outcond);

                    if (process.JobName == "RSCIS003DP" || process.JobName == "RSCIS004DP" || process.JobName == "RSCIS005DP" || process.JobName == "RSCIS006DP")
                    {
                        XElement docond = new XElement("DOCOND");
                        XAttribute namedocond = new XAttribute("NAME", name.Value + "-LB");

                        XElement doe = new XElement("DO");
                        XAttribute action = new XAttribute("ACTION", "SPCYC");

                        docond.Add(namedocond);
                        docond.Add(odate);
                        docond.Add(sign);

                        doe.Add(action);

                        var on = element.Descendants().Where(n => n.Name.LocalName == "ON" && n.Attribute("CODE").Value.Equals("*MSG_Sucesso*")).Single();
                        on.Add(docond);
                        on.Add(doe);
                    }
                }

                var parameter4 = element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT" && n.Attribute("EXP").Value.StartsWith("%%PARM4")).Single().Attribute("EXP");
                var parameter5 = element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT" && n.Attribute("EXP").Value.StartsWith("%%PARM5")).Single().Attribute("EXP");

                if (process.JobName == "RSCIS064DP")
                {
                    parameter4.Value = "%%PARM4=-tipo:agendar";
                    parameter5.Value = "%%PARM5=-sistema:" + controlMConfiguration.SystemId;
                }
                else
                {
                    parameter4.Value = "%%PARM4=-tipo:comando";
                    parameter5.Value = "%%PARM5=-id:" + process.ProcessId;
                }

                var parameter9 = element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT" && n.Attribute("EXP").Value.StartsWith("%%PARM9")).Single().Attribute("EXP");
                parameter9.Value = "%%PARM9=" + controlMConfiguration.Type;

                var domail = element.Descendants().Where(n => n.Name.LocalName == "DOMAIL");

                foreach (var mail in domail)
                {
                    string message = mail.Attribute("MESSAGE").Value;

                    message = string.Format(message, description.ToUpper());
                    message = message.Length.ToString().PadLeft(4, '0') + message;

                    if (process.JobName == "RSCIS003DP" || process.JobName == "RSCIS004DP" || process.JobName == "RSCIS005DP" || process.JobName == "RSCIS006DP")
                    {
                        message = string.Format("Arquivo {0} não encontrado no diretório de origem, verificar log anexo. 00000020Jobname - %%JOBNAME 00000016Data -  %%ODATE 00000013Hora - %%TIME00000016IBBA - Control-M", process.ProcessName);
                        mail.Attribute("MESSAGE").Value = message.Length.ToString().PadLeft(4, '0') + message;
                        mail.Attribute("SUBJECT").Value = "[CTM] *** Alerta: Erro: RSCI: Arquivo não encontrado no diretório de origem ***";
                    }
                    else
                    {
                        mail.Attribute("MESSAGE").Value = message;
                        mail.Attribute("SUBJECT").Value = string.Format(mail.Attribute("SUBJECT").Value, jobName);
                    }
                }

                if (process.JobName == "RSCIS003DP" || process.JobName == "RSCIS004DP" || process.JobName == "RSCIS005DP" || process.JobName == "RSCIS006DP")
                {
                    var on = element.Descendants().Where(n => n.Name.LocalName == "ON" && n.Attribute("CODE").Value.Equals("*MSG_Semarq_Prog*")).Single();
                    on.Attribute("CODE").Value = "*MSG_SemArq*";
                    on.Element("DO").Attribute("ACTION").Value = "OK";
                    on.Element("DOMAIL").Remove();

                    on = element.Descendants().Where(n => n.Name.LocalName == "ON" && n.Attribute("CODE").Value.Equals("*MSG_ErroProg*")).Single();
                    on.Attribute("CODE").Value = "*MSG_Erromov*";

                    element.Attribute("CYCLIC").Value = "1";
                    element.Add(new XAttribute("DOCLIB", @"\\BBACTMC2\JOBCTL\%%PARM9.\RSCI\DOCLIB"));
                    element.Add(new XAttribute("DOCMEM", "%%JOBNAME..TXT"));
                    element.Attribute("INTERVAL").Value = "00005M";
                    element.Attribute("MAXWAIT").Value = "0";
                    element.Attribute("MEMNAME").Value = string.Format("RSCIS003D{0}.CMD", controlMConfiguration.JobNameSuffix);
                    element.Add(new XAttribute("TIMEFROM", "0100"));
                    element.Add(new XAttribute("TIMETO", ">"));
                    element.Attribute("WEEKSCAL").Value = "WORKDAYS";
                    element.Attribute("WEEKDAYS").Remove();
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT" && n.Attribute("EXP").Value.StartsWith("%%PARM2")).Single().Attribute("EXP").Value = "%%PARM2=%%DATE";
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT" && n.Attribute("EXP").Value.StartsWith("%%PARM3")).Single().Attribute("EXP").Value = "%%PARM3=%%TIME";
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT" && n.Attribute("EXP").Value.StartsWith("%%PARM4")).Single().Attribute("EXP").Value = "%%PARM4=" + process.ProcessName;
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT" && n.Attribute("EXP").Value.StartsWith("%%PARM5")).Single().Remove();
                    element.Elements().Where(n => n.Name.LocalName == "AUTOEDIT" && n.Attribute("EXP").Value.StartsWith("%%PARM6")).Single().Remove();
                }

                tableElement.Add(element);
            }

            document.Save(fileName);
        }

        private string RemoveAccents(string text)
        {
            string s = text.Normalize(NormalizationForm.FormD);

            StringBuilder sb = new StringBuilder();

            for (int k = 0; k < s.Length; k++)
            {
                UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(s[k]);

                if (uc != UnicodeCategory.NonSpacingMark)
                {
                    sb.Append(s[k]);
                }
            }

            return sb.ToString();
        }

        private string ReplaceJobName(string jobName, string jobNameSuffix)
        {
            string job = jobName;

            if (jobName != "LIBERA_RISCO_CREDITO" && jobName != "LIBERA_BUILD_FORGE_RISCO")
            {
                job = jobName.Substring(0, jobName.Length - 1) + jobNameSuffix;
            }

            return job;
        }

        private string GetGroupIds()
        {
            StringBuilder builder = new StringBuilder();

            foreach (var group in _groupsSimio)
            {
                builder.Append(group.GroupId + ",");
            }

            return builder.ToString().Substring(0, builder.ToString().Length - 1);
        }

        #endregion

        private void PopulateCombo()
        {
            foreach (SimioConfigurationElement item in _environmentConfiguration.Simio)
            {
                ddlEnvironmentSimio.Items.Add(item.ServerName);
            }

            foreach (ControlMConfigurationElement item in _environmentConfiguration.ControlM)
            {
                ddlEnvironmentControlM.Items.Add(item.Name);
            }
        }

        private void ListAllJobs(XDocument document)
        {
            var jobs = (from n in document.Descendants()
                        where n.Name.LocalName == "JOB"
                        select new { JobName = n.Attribute("JOBNAME").Value, Description = n.Attribute("DESCRIPTION").Value }).Distinct().OrderBy(j => j.JobName);

            foreach (var item in jobs)
            {
                File.AppendAllText(@"c:\teste\jobs.txt", item.JobName + "|" + item.Description + System.Environment.NewLine);
            }
        }

        private void SetStyle(ProcessEntity process, Node node)
        {
            if (process.TaskType == "Dummy")
            {
                SetStyle(node, Shape.Box, process.GroupName);
            }
            else
            {
                SetStyle(node, Shape.Circle, process.GroupName);
            }
        }

        private void SetStyle(Node node, Shape shape, string groupId)
        {
            int seed = 0;
            int.TryParse(groupId, out seed);

            if (seed == 0 && groupId != "0")
            {
                int.TryParse(groupId.Substring(groupId.Length - 2), out seed);
            }

            if (seed == 0)
            {
                seed = 1000; //System.Text.Encoding.ASCII.GetBytes(groupId).Sum(b => b);
            }

            if (groupId == "liberarisco")
                seed = 80;

            if (groupId == "NORISKSGFI")
                seed = 50;

            Random rnd = new Random(seed);

            Color color = new Color((byte)rnd.Next(byte.MinValue, byte.MaxValue), (byte)rnd.Next(byte.MinValue, byte.MaxValue), (byte)rnd.Next(byte.MinValue, byte.MaxValue), (byte)rnd.Next(byte.MinValue, byte.MaxValue));

            SetStyle(node, shape, color);
        }

        private void SetStyle(Node node, Shape shape, Color color)
        {
            node.Attr.Shape = shape;
            node.Attr.Fillcolor = color;
            node.Attr.Fontcolor = Color.Black;
        }

        #endregion
    }

    public class GroupDB
    {
        public int GroupId { get; set; }
        public string GroupName { get; set; }
        public int PredecessorId { get; set; }
    }

    public class ProcessDB
    {
        public int GroupId { get; set; }
        public int ProcessId { get; set; }
        public string ProcessName { get; set; }
        public string JobName { get; set; }
        public int PredecessorId { get; set; }
    }
}
